package com.dong.ui.view;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.dong.common.constant.PropertiesConst;
import com.dong.common.pojo.ResultVO;
import com.dong.common.util.PropertiesUtils;
import com.dong.common.util.RequestUtils;
import com.dong.common.view.CommonView;
import com.dong.ui.component.CommonFrame;
import com.dong.ui.component.LinkLabel;
import com.dong.ui.constant.RouterConst;
import com.dong.ui.util.ComponentUtils;
import com.dong.ui.util.FontUtils;
import com.dong.ui.util.MessageUtils;
import com.dong.ui.util.RouterUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @description:
 * @author: 陈瑞东
 * @create: 2021-08-24 11:36
 */
@org.springframework.stereotype.Component(RouterConst.VIEW_LOGIN)
public class LoginFrame extends CommonFrame implements CommonView {

    /*==================组件==================*/
    private static final int WIDTH = 520;
    private static final int HEIGHT = 380;

    private JLabel titleLabel;

    private JLabel nameJLabel;
    private JTextField nameJTextField;

    private JLabel pwdJLabel;
    private JPasswordField pwdJTextField;

    private JCheckBox autoLoginCheckBox;
    private JCheckBox rememberMeCheckBox;
    private LinkLabel regLabel;

    private JButton loginBtn;
    /*==================组件==================*/
    /*==================参数==================*/

    private boolean rememberMe;
    private boolean autoLogin;
    private String username;
    private String password;


    /*==================参数==================*/
    /*==================标志==================*/
    boolean canLogin = true;

    /*==================标志==================*/

    @Override
    public void init(Map<String, Object> params) {
        // 设置标题
        setTitle("登录");


        handleView();

        // 设置大小
        setSize(new Dimension(WIDTH, HEIGHT));
        // 设置不可改变大小
        setResizable(false);
        // 设置居中
        setLocationRelativeTo(null);
        // 设置可见
        setVisible(true);

        handleAction();
    }

    @Override
    public void initComponent() {
        titleLabel = new JLabel("欢迎使用菜单管理系统");
        titleLabel.setFont(FontUtils.TITLE_FONT);

        nameJLabel = new JLabel("用户名");
        nameJTextField = new JTextField(username, 20);

        pwdJLabel = new JLabel("密  码");
        pwdJTextField = new JPasswordField(password, 20);

        autoLoginCheckBox = new JCheckBox("自动登录", autoLogin);
        rememberMeCheckBox = new JCheckBox("记住密码", rememberMe);

        regLabel = new LinkLabel("注册账号");

        loginBtn = new JButton("登    录");
    }

    @Override
    public void initParams() {
        ResultVO<Map<String,String>> result = (ResultVO<Map<String,String>>) RequestUtils.sendRequest("/user/configParams", null);
        Map<String, String> data = result.getData();
        this.username = data.get("username");
        this.password = data.get("password");
        this.rememberMe = Boolean.parseBoolean(data.get("rememberMe"));
        this.autoLogin = Boolean.parseBoolean(data.get("autoLogin"));
    }

    @Override
    public void handleView() {
        initParams();
        initComponent();

        // 背景容器
        JPanel bgPabel = new JPanel();

        // 外层水平容器
        Box hBox = Box.createHorizontalBox();

        // 外层垂直容器
        Box vBox = Box.createVerticalBox();

        // 标题水平容器
        Box titleBox = Box.createHorizontalBox();

        titleBox.add(titleLabel);

        // 用户名输入框水平容器
        Box nameBox = ComponentUtils.lineInput(nameJLabel, nameJTextField, 15);

        // 密码输入框水平容器
        Box pwdBox = ComponentUtils.lineInput(pwdJLabel, pwdJTextField, 15);

        // 选项行水平容器
        Box optionBox = Box.createHorizontalBox();

        optionBox.add(autoLoginCheckBox);
        optionBox.add(Box.createHorizontalStrut(15));
        optionBox.add(rememberMeCheckBox);
        optionBox.add(Box.createHorizontalStrut(30));
        optionBox.add(regLabel);

        // 登录按钮水平容器
        Box loginBox = Box.createHorizontalBox();
        // 使用边界布局使btn占满该行
        JPanel loginBtnPanel = new JPanel(new BorderLayout());

        loginBox.add(loginBtnPanel);
        loginBtnPanel.add(loginBtn);

        // 添加至外层垂直容器
        vBox.add(Box.createVerticalStrut(30));
        vBox.add(titleBox);
        vBox.add(Box.createVerticalStrut(25));
        vBox.add(nameBox);
        vBox.add(Box.createVerticalStrut(20));
        vBox.add(pwdBox);
        vBox.add(Box.createVerticalStrut(20));
        vBox.add(optionBox);
        vBox.add(Box.createVerticalStrut(20));
        vBox.add(loginBox);
        vBox.add(Box.createVerticalStrut(35));

        // 将垂直容器添加至水平容器
        hBox.add(Box.createHorizontalStrut(40));
        hBox.add(vBox);
        hBox.add(Box.createHorizontalStrut(40));

        // 将水平容器添加至背景容器
        bgPabel.add(hBox);

        // 添加容器至该窗体
        this.add(bgPabel);
    }

    @Override
    public void handleAction() {
        // 处理自动登录
        autoLoginEvent();
        // 点击自动登录选项事件
        autoLoginClickEvent();
        // 点击注册账号事件
        regLabelClickEvent();
        // 点击登录事件
        loginBtnClickEvent();
        // 回车事件
        EnterEvent();
    }

    /**
     * 点击"登录"按钮事件
     * 1. 调用登录方法:
     */
    private void loginBtnClickEvent() {
        loginBtn.addActionListener(e -> {
            login();
        });
    }

    /**
     * 键盘回车事件
     * 1. 调用登录方法
     */
    private void EnterEvent() {
        // 给指定控件添加回车事件
        Component[] components = new Component[] {nameJTextField, pwdJTextField, rememberMeCheckBox, autoLoginCheckBox};
        for (Component component : components) {
            component.addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent e) {
                    if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                        login();
                    }
                }
            });
        }
    }

    /**
     * 处理自动登录
     * 1. 如果"自动登录"上次被勾选，则直接调用登录方法
     */
    private void autoLoginEvent() {
        if (this.autoLogin) {
            login();
        }
    }

    /**
     * 点击"注册账号"事件
     * 1. 隐藏该窗体
     * 2. 创建注册窗体
     */
    private void regLabelClickEvent() {
        this.regLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                // 隐藏该窗体（注意：此处的this不是frame）
                setVisible(false);
                // 显示注册窗体
                RouterUtils.router(RouterConst.VIEW_REG);
            }
        });
    }

    /**
     * 点击"自动登录"选项事件
     * 1. 从未选中状态至选中状态时，连同"记住密码"一起选中
     */
    private void autoLoginClickEvent() {
        autoLoginCheckBox.addActionListener(e -> {
            // 判断是否选中（此处为点击后的状态）
            if (autoLoginCheckBox.isSelected()) {
                // 选中"记住密码"
                rememberMeCheckBox.setSelected(true);
            }
        });
    }


    /**
     * 登录方法:
     *  1. 设置登录标志位为false
     *  2. 设置鼠标图标为加载
     *  3. 开始登录
     *       登录成功:
     *           1. 关闭该窗体
     *           2. 修改配置文件
     *           3. 创建主页窗体
     *       登录失败:
     *           1. 弹出提示框
     *
     *  4. 清空密码框——直接处理登出时的状态
     *  5. 设置鼠标图标为默认
     *  6. 设置登录标志位为true
     */
    private void login() {
        // 如果不能点击登录按钮，直接返回
        if (!this.canLogin) {
            return;
        }
        requestBegin();

        String username = nameJTextField.getText();
        String password = new String(pwdJTextField.getPassword());
        String isAutoLogin = String.valueOf(autoLoginCheckBox.isSelected());
        String isRememberMe = String.valueOf(rememberMeCheckBox.isSelected());
        if (!preLogin(username, password)) {
            requestEnd();
            return;
        }
        Map<String, Object> params = new HashMap<String, Object>() {{
            put("username", username);
            put("password", password);
        }};
        ResultVO<Void> result = (ResultVO<Void>) RequestUtils.sendRequest("user/login", params);
        if (result.isSuccess()) {
            // 登录成功
//            MessageUtils.showMessageDialog(this, "登录成功!", "提示", JOptionPane.INFORMATION_MESSAGE);
            // 修改配置文件
            // 当选上"记住密码"的时候，填充密码，否则，清空
            if (Boolean.parseBoolean(isRememberMe)) {
                PropertiesUtils.setValue(PropertiesConst.USER_CONFIG_NAME, PropertiesConst.USER_KEY_PASSWORD, password);
            } else {
                PropertiesUtils.setValue(PropertiesConst.USER_CONFIG_NAME, PropertiesConst.USER_KEY_PASSWORD, "");
            }
            PropertiesUtils.setValue(PropertiesConst.USER_CONFIG_NAME, PropertiesConst.USER_KEY_USERNAME, username);
            PropertiesUtils.setValue(PropertiesConst.USER_CONFIG_NAME, PropertiesConst.USER_KEY_AUTOLOGIN, isAutoLogin);
            PropertiesUtils.setValue(PropertiesConst.USER_CONFIG_NAME, PropertiesConst.USER_KEY_REMEMBERME, isRememberMe);

            RouterUtils.router(RouterConst.VIEW_HOME);
            this.setVisible(false);
        } else {
            // 登录失败
            MessageUtils.showMessageDialog(this, result.getMessage(), "登录失败", JOptionPane.WARNING_MESSAGE);
        }

        pwdJTextField.setText("");
        requestEnd();
    }

    /**
     * 请求前的参数验证
     * @param username
     * @param password
     * @return
     */
    private boolean preLogin(String username, String password) {
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            MessageUtils.showMessageDialog(this, "用户名或密码不能为空！", "登录失败", JOptionPane.WARNING_MESSAGE);
            return false;
        }
        return true;
    }

    /**
     * 请求开始
     */
    private void requestBegin() {
        // 设置鼠标图标为加载图标
        this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
        // 设置不能登录
        this.canLogin = false;
    }

    /**
     * 请求结束
     */
    private void requestEnd() {
        // 还原鼠标图标
        this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        // 设置可以登录
        this.canLogin = true;
    }

}
